`timescale 1ns/1ns

`define HASH_WIDTH 1024 
`define DATA_WIDTH 256
`define G_x_256r1 256'h6B17D1F2_E12C4247_F8BCE6E5_63A440F2_77037D81_2DEB33A0_F4A13945_D898C296
`define G_y_256r1 256'h4FE342E2_FE1A7F9B_8EE7EB4A_7C0F9E16_2BCE3357_6B315ECE_CBB64068_37BF51F5
`define G_x_sm2 256'h32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7
`define G_y_sm2 256'hBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0


module ecc_core(input 	 			  	     clk,
				input	 				     rst_n,
				
				input 	 				     Start,
				output reg	 			     Done,
				input      [1:0]			 FunSel,                //  000 signature  001 verify  010 keypair																
				input 						 curve_sel,				//	0 256r1    1 sm2
				input      [`DATA_WIDTH-1:0] dA,   					//私钥
				input      [`DATA_WIDTH-1:0] PA_x, 					//公钥
				input      [`DATA_WIDTH-1:0] PA_y, 					//公钥			
			    input      [`DATA_WIDTH-1:0] random_k, 				//for signature
				input      [`DATA_WIDTH-1:0] s_verify, 				//验签需要的s
				input      [`DATA_WIDTH-1:0] r_verify, 				//验签需要的r
				output     [`DATA_WIDTH-1:0] s,	   				 	//签名生成的s，kp的x，pk的x
				output     [`DATA_WIDTH-1:0] r,        				//签名生成的r，kp的y，pk的y
				input 						 Hv_done,
				input      [`DATA_WIDTH-1:0] Hv_r,
				output reg		   			 bingo,
				output reg [2:0]             State,
				output reg [7:0]			 error
			   );

//wire [`DATA_WIDTH-1:0] G_x,G_y;

//wire [`DATA_WIDTH-1:0] n;

//////////////////////////////functional////////////////////////////////

wire [`DATA_WIDTH-1:0] x,y;//不同个状态连接不同的值

//wire [`DATA_WIDTH-1:0] mod_p;//标量乘连p，签名验签连n；
wire mod;

wire MM_enable,INV_enable,func;

wire [21:0] r_sel;//不同个状态连接不同的值

wire [7:0] M_sel_a,M_sel_b,A_sel_a,A_sel_b;//不同个状态连接不同的值

wire [1:0] I_sel;//不同个状态连接不同的值

wire [`DATA_WIDTH-1:0] t1,t2,t3,t4,t5,t7;

wire MM_end_flag,INV_end_flag;

//wire [`DATA_WIDTH-1:0] hv;
/////////////////////////////MLcozScalar////////////////////////////////

wire ML_enable;

wire [`DATA_WIDTH-1:0] ML_k;//验签KG是k1，KP是k2；签名是randomk，密钥交换是dA；

wire [21:0] ML_r_sel;

wire [7:0] ML_M_sel_a,ML_M_sel_b,ML_A_sel_a,ML_A_sel_b;

wire [1:0] ML_I_sel;

wire ML_MM_enable,ML_INV_enable,ML_func;

wire ML_end_flag;

/////////////////////////////signature//////////////////////////////////

reg enable_sign,enable_pair;

//wire sign_end_flag;

wire [10:0] state_sign,next_state_sign;

wire [`DATA_WIDTH-1:0] sign_r,sign_ss,sign_s;

wire sign_ML_enable;

wire [21:0] sign_r_sel;

wire [7:0] /*sign_M_sel_a,sign_M_sel_b,*/sign_A_sel_a,sign_A_sel_b;

wire [1:0] sign_I_sel;

wire sign_INV_enable;/*sign_func,*///modn;

wire sign_func;

wire re_t1,re_t7;

//wire sign_checks_no;

////////////////////////////verify_sign/////////////////////////////////

reg enable_verify;

//wire verify_end_flag;

wire [13:0] state_verify,next_state_verify;

//wire verify_bingo/*,verify_invalid*/;

wire verify_ML_enable,verify_INV_enable;

wire [1:0] verify_I_sel;

wire verify_MM_enable,verify_func;

wire [21:0] verify_r_sel;

wire [7:0] verify_M_sel_a,verify_M_sel_b,verify_A_sel_a,verify_A_sel_b;

wire [`DATA_WIDTH-1:0] verify_k1,verify_k2,verify_kg_y;

wire [`DATA_WIDTH-1:0] sm3_e;

wire verify_checkRr_no;

////////////////////////////////ecc_core_ctrl///////////////////////////

parameter IDLE      = 3'd0,
		  PUBLICKEY = 3'd1,
		  SIGN      = 3'd2,
		  VERIFY    = 3'd3,
		  KEYPAIR   = 3'd4;
		  //FINISH    = 3'd5;

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		State         <= 3'd0;
		enable_sign   <= 1'b0;
		enable_pair   <= 1'b0;
		enable_verify <= 1'b0;
		Done          <= 1'b0;
		bingo         <= 1'b0;
		error 		  <= 8'b0;
	end
	else
	begin
		case(State)
		IDLE      : 
					begin
						if(Start)
							begin
								if(FunSel == 2'b00)
									begin
										State 		  <= SIGN;
										enable_sign   <= 1'b1;
										enable_pair   <= 1'b0;
										enable_verify <= 1'b0;
										Done          <= 1'b0;
										bingo         <= 1'b0;
										error		  <= 8'b0;
									end
								else if(FunSel == 2'b01)
									begin
										State 		  <= VERIFY;
										enable_sign   <= 1'b0;
										enable_pair   <= 1'b0;
										enable_verify <= 1'b1;
										Done          <= 1'b0;
										bingo         <= 1'b0;
										error		  <= 8'b0;
									end
								else if(FunSel == 2'b10)
									begin
										State 		  <= KEYPAIR;
										enable_sign   <= 1'b0;
										enable_pair   <= 1'b1;
										enable_verify <= 1'b0;
										Done          <= 1'b0;
										bingo         <= 1'b0;
										error		  <= 8'b0;
									end
								else//(FunSel == 2'b11)
									begin
										State 		  <= PUBLICKEY;
										enable_sign   <= 1'b0;
										enable_pair   <= 1'b1;
										enable_verify <= 1'b0;
										Done          <= 1'b0;
										bingo         <= 1'b0;
										error		  <= 8'b0;
									end
								/*else
									begin
										State 		  <= IDLE;
										enable_sign   <= 1'b0;
										enable_pair   <= 1'b0;
										enable_verify <= 1'b0;
										Done          <= 1'b0;
										bingo         <= 1'b0;
										error		  <= 8'b0;
									end
								*/
							end
						else
							begin
								State 		  <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error		  <= 8'b0;
							end
					end
		PUBLICKEY : 
					begin
						/*if((state_sign==11'b000_0000_0010)&&(next_state_sign==11'b000_0000_0001))//state == CHOOSE && next_state == IDLE
						begin
							State <= IDLE;
							enable_sign   <= 1'b0;
							enable_pair   <= 1'b0;
							enable_verify <= 1'b0;
							Done          <= 1'd1;
							bingo         <= 1'b0;
							error[7:2]	  <= 6'b0;
							error[1]      <= 1'b1;
							error[0]	  <= 1'b1;
						end
						else if((state_sign==11'b000_0000_0100)&&(next_state_sign==11'b000_0000_0001))//state == KG && next_state == IDLE
						begin
							State <= IDLE;
							enable_sign   <= 1'b0;
							enable_pair   <= 1'b0;
							enable_verify <= 1'b0;
							Done          <= 1'd1;
							bingo         <= 1'b0;
							error 		  <= 8'b0;
						end
						*/
						if(next_state_sign == 11'b000_0000_0001)
						begin
							if(state_sign==11'b000_0000_0010)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'd1;
								bingo         <= 1'b0;
								error[7:2]	  <= 6'b0;
								error[1]      <= 1'b1;
								error[0]	  <= 1'b1;
							end
							else if(state_sign==11'b000_0000_0100)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'd1;
								bingo         <= 1'b0;
								error 		  <= 8'b0;
							end
							else
							begin
								State 		  <= PUBLICKEY;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error         <= 8'b0;
							end
						end
						else
						begin
							State 		  <= PUBLICKEY;
							enable_sign   <= 1'b0;
							enable_pair   <= 1'b0;
							enable_verify <= 1'b0;
							Done          <= 1'b0;
							bingo         <= 1'b0;
							error         <= 8'b0;
						end
					end
		SIGN      :
					begin
						if(next_state_sign==11'b00000000001)
						begin
							if(state_sign==11'b00000000010)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7]	  <= 1'b1;
								error[6:1]	  <= 6'b0;
								error[0]	  <= 1'b1;
							end
							else if(state_sign==11'b00000010000)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7]	  <= 1'b0;
								error[6]	  <= 1'b1;
								error[5:1]	  <= 5'b0;
								error[0]	  <= 1'b1;
							end
							else if(state_sign==11'b100_0000_0000)
							begin
								if(t1 == 256'h0)
								begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:6]	  <= 2'b0;
								error[5]	  <= 1'b1;
								error[4:1]	  <= 4'b0;
								error[0]	  <= 1'b1;
								end
								else
								begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error		  <= 8'b0;	
								end
							end
							else
							begin
								State 		  <= SIGN;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error		  <= 8'b0;
							end
						end
						/*
						if((state_sign==11'b00000000010)&&(next_state_sign==11'b00000000001))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7]	  <= 1'b1;
								error[6:1]	  <= 6'b0;
								error[0]	  <= 1'b1;
							end
						else if((state_sign==11'b00000010000)&&(next_state_sign==11'b00000000001))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7]	  <= 1'b0;
								error[6]	  <= 1'b1;
								error[5:1]	  <= 5'b0;
								error[0]	  <= 1'b1;
							end
						else if((state_sign==11'b100_0000_0000)&&(next_state_sign==11'b00000000001)&&(t1 == 256'h0))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:6]	  <= 2'b0;
								error[5]	  <= 1'b1;
								error[4:1]	  <= 4'b0;
								error[0]	  <= 1'b1;
							end
						else if((state_sign==11'b100_0000_0000)&&(next_state_sign==11'b000_0000_0001)&&(t1 != 256'h0))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error		  <= 8'b0;
							end
						*/
						else
							begin
								State 		  <= SIGN;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error		  <= 8'b0;
							end
					end
		VERIFY    :
					begin
						if(next_state_verify==14'b00_0000_0000_0001)
						begin
							if(state_verify==14'b00_0000_0000_0010)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:5]    <= 3'b0;
								error[4]	  <= 1'b1;
								error[3:1]	  <= 3'b0;
								error[0]	  <= 1'b1;
							end
							else if(state_verify==14'b00_0000_0000_0100)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:4]    <= 4'b0;
								error[3]	  <= 1'b1;
								error[2:1]	  <= 2'b0;
								error[0]	  <= 1'b1;
							end
							else if(state_verify==14'b00_1000_0000_0000)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:3]    <= 5'b0;
								error[2]	  <= 1'b1;
								error[1]	  <= 1'b0;
								error[0]	  <= 1'b1;
							end
							else if(state_verify==14'b00_0000_0000_1100)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:3]    <= 5'b0;
								error[2]	  <= 1'b1;
								error[1]	  <= 1'b0;
								error[0]	  <= 1'b1;
							end
							else if(state_verify==14'b10_0000_0000_0000) 
							begin
								if(verify_checkRr_no == 1'b0)
								begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b1;
								error		  <= 8'b0;
								end
								else
								begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:3]    <= 5'b0;
								error[2]	  <= 1'b1;
								error[1]	  <= 1'b0;
								error[0]	  <= 1'b1;
								end
							end
							else
							begin
								State 		  <= VERIFY;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error         <= 8'b0;
							end
						end
						/*
						if((state_verify==14'b00_0000_0000_0010)&&(next_state_verify==14'b00_0000_0000_0001))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:5]    <= 3'b0;
								error[4]	  <= 1'b1;
								error[3:1]	  <= 3'b0;
								error[0]	  <= 1'b1;
							end
						else if((state_verify==14'b00_0000_0000_0100)&&(next_state_verify==14'b00_0000_0000_0001))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:4]    <= 4'b0;
								error[3]	  <= 1'b1;
								error[2:1]	  <= 2'b0;
								error[0]	  <= 1'b1;
							end
						else if(((state_verify==14'b00_1000_0000_0000)&&(next_state_verify==14'b00_0000_0000_0001))||((state_verify==14'b10_0000_0000_0000)&&(next_state_verify==14'b00_0000_0000_0001)&&(verify_checkRr_no==1'b1))||((state_verify==14'b00_0000_0000_1100)&&(next_state_verify==14'b00_0000_0000_0001)))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:3]    <= 5'b0;
								error[2]	  <= 1'b1;
								error[1]	  <= 1'b0;
								error[0]	  <= 1'b1;
							end
						else if((state_verify==14'b10_0000_0000_0000)&&(next_state_verify==14'b00_0000_0000_0001)&&(verify_checkRr_no == 1'b0))
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b1;
								error		  <= 8'b0;
							end
						*/
						else
							begin
								State 		  <= VERIFY;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error         <= 8'b0;
							end
					end
		KEYPAIR   :
					begin
						/*if((state_sign==11'b000_0000_0010)&&(next_state_sign==11'b000_0000_0001))//state == CHOOSE && next_state == IDLE
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:2]	  <= 6'b0;
								error[1]      <= 1'b1;
								error[0]	  <= 1'b1;
							end
						else if((state_sign==11'b000_0000_0100)&&(next_state_sign==11'b000_0000_0001))//state == KG && next_state == IDLE
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error 		  <= 8'b0;
							end
						*/
						if(next_state_sign == 11'b000_0000_0001)
						begin
							if(state_sign==11'b000_0000_0010)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error[7:2]	  <= 6'b0;
								error[1]      <= 1'b1;
								error[0]	  <= 1'b1;
							end
							else if(state_sign==11'b000_0000_0100)
							begin
								State <= IDLE;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b1;
								bingo         <= 1'b0;
								error 		  <= 8'b0;
							end
							else
							begin
								State         <= KEYPAIR;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error		  <= 8'b0;
							end
						end
						else
							begin
								State         <= KEYPAIR;
								enable_sign   <= 1'b0;
								enable_pair   <= 1'b0;
								enable_verify <= 1'b0;
								Done          <= 1'b0;
								bingo         <= 1'b0;
								error		  <= 8'b0;
							end
					end
		/*FINISH    :
					begin
						State <= IDLE;
						enable_sign   <= 1'b0;
						enable_pair   <= 1'b0;
						enable_verify <= 1'b0;
						Done          <= 1'b0;
						bingo         <= 1'b0;
					end*/
		default   :
					begin
						State <= IDLE;
						enable_sign   <= 1'b0;
						enable_pair   <= 1'b0;
						enable_verify <= 1'b0;
						Done          <= 1'b0;
						bingo         <= 1'b0;
						error 		  <= 8'b0;
					end
		endcase
	end
end

////////////////////////////////////////////////////////////////////////

//assign G_x = (curve_sel == 1'b0) ? 256'h6B17D1F2_E12C4247_F8BCE6E5_63A440F2_77037D81_2DEB33A0_F4A13945_D898C296 : 256'h32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7;

//assign G_y = (curve_sel == 1'b0) ? 256'h4FE342E2_FE1A7F9B_8EE7EB4A_7C0F9E16_2BCE3357_6B315ECE_CBB64068_37BF51F5 : 256'hBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0;

//assign G_x = (curve_sel == 1'b0) ? `G_x_256r1 : `G_x_sm2;

//assign G_y = (curve_sel == 1'b0) ? `G_y_256r1 : `G_y_sm2;

//assign x = (State == KEYPAIR) ? PA_x : ((state_verify == 15'b000000100000000) ? PA_x : G_x);

assign x = (State == KEYPAIR) ? PA_x : ((state_verify == 14'b00000100000000) ? PA_x : ((curve_sel == 1'b0) ? `G_x_256r1 : `G_x_sm2));

//assign y = (State == KEYPAIR) ? PA_y : ((state_verify == 15'b000000100000000) ? PA_y : G_y);

assign y = (State == KEYPAIR) ? PA_y : ((state_verify == 14'b00000100000000) ? PA_y : ((curve_sel == 1'b0) ? `G_y_256r1 : `G_y_sm2));

assign mod = ((state_sign == 11'b00000000100) || (state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_verify == 14'b00010000000000)) ? 1'b0 : 1'b1;

assign MM_enable = (State == VERIFY) ? (((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000)) ? ML_MM_enable : verify_MM_enable) : ML_MM_enable;

assign INV_enable = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_INV_enable : ((State == VERIFY) ? verify_INV_enable : sign_INV_enable);

assign func = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_func : ((State == VERIFY) ? verify_func : sign_func);

assign r_sel = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_r_sel : ((State == VERIFY) ? verify_r_sel : sign_r_sel);

assign M_sel_a = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_M_sel_a : ((State == VERIFY) ? verify_M_sel_a : 8'h0);

assign M_sel_b = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_M_sel_b : ((State == VERIFY) ? verify_M_sel_b : 8'h0);

assign A_sel_a = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_A_sel_a : ((State == VERIFY) ? verify_A_sel_a : sign_A_sel_a);

assign A_sel_b = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_A_sel_b : ((State == VERIFY) ? verify_A_sel_b : sign_A_sel_b);

assign I_sel = ((state_verify == 14'b00000010000000) || (state_verify == 14'b00000100000000) || (state_sign == 11'b00000000100)) ? ML_I_sel : ((State == VERIFY) ? verify_I_sel : sign_I_sel);

assign ML_enable = (State == VERIFY) ? verify_ML_enable : sign_ML_enable;

assign ML_k = (State == VERIFY) ? ((state_verify == 14'b00000010000000) ? verify_k1 : verify_k2) : (((State == KEYPAIR) || (State == PUBLICKEY)) ? dA : random_k);

assign s = (FunSel == 3'b000) ? t1 : (((FunSel == 3'b010) || (FunSel == 3'b011)) ? t3 : `DATA_WIDTH'd0);

assign r = (FunSel == 3'b000) ? t2 : (((FunSel == 3'b010) || (FunSel == 3'b011)) ? t7 : `DATA_WIDTH'd0);

//assign hv = (curve_sel == 1'b0) ? sha512_o : sm3_r;

functional modular(.clk(clk),
				   .rst_n(rst_n),
				   .curve_sel(curve_sel),
				   .mod(mod),
				   .re_t1(re_t1),
				   .re_t7(re_t7),
				   .x1(x),
				   .y1(y),
				   .k(random_k),//只是模逆需要，求k的逆
				   //.p(mod_p),//标量乘连p，签名验签连n；
				   //.a(a),
				   .dA(dA),
				   .Hv_r(Hv_r),
				   .sm3_e(sm3_e),
				   .r(sign_r),
				   .ss(sign_ss),
				   .s(sign_s),
				   .v_s(s_verify),
				   .v_r(r_verify),
				   .k1(verify_k1),
				   .kg_y(verify_kg_y),
				   .MM_enable(MM_enable),//做标量乘连标量乘，验签时连标量乘或者点加
				   .inv_enable(INV_enable),//做标量乘连标量乘，签名和验签各额外有一次
				   .func(func),//签名验签连标量乘或验签的点加
				   //.modn(modn),
				   .r_sel(r_sel),
				   .M_sel_a(M_sel_a),
				   .M_sel_b(M_sel_b),
				   .A_sel_a(A_sel_a),
				   .A_sel_b(A_sel_b),
				   .I_sel(I_sel),
				   .t1(t1),
				   .t2(t2),
				   .t3(t3),
				   .t4(t4),
				   .t5(t5),
				   .t7(t7),
				   .MM_end_flag(MM_end_flag),
				   .INV_end_flag(INV_end_flag)
				  );
/*
sha512 SHA(.clk(clk),
		   .rstn(rst_n),
		   .text_i_1024(sha512_M),
		   .SHA512_result_o(sha512_result_o),
		   .busy(sha512_busy),
		   .first_round(sha512_first_round),
		   .last_round(sha512_last_round),
		   .start(sha512_start),
		   .round_end_flag(sha512_round_end_flag),
		   .done(sha512_done)
		  );
*/

MLcozScalar pointmul(.clk(clk),
					 .rst_n(rst_n),
					 .enable(ML_enable),
					 .k(ML_k),
					 .MM_end_flag(MM_end_flag),
					 .INV_end_flag(INV_end_flag),
					 .error(error[0]),
					 .r_sel(ML_r_sel),
					 .M_sel_a(ML_M_sel_a),
					 .M_sel_b(ML_M_sel_b),
					 .A_sel_a(ML_A_sel_a),
					 .A_sel_b(ML_A_sel_b),
					 .I_sel(ML_I_sel),
					 .MM_enable(ML_MM_enable),
					 .INV_enable(ML_INV_enable),
					 .func(ML_func),
					 .end_flag(ML_end_flag)
					);
					
signature sign(.clk(clk),
			   .rst_n(rst_n),
			   .curve_sel(curve_sel),
			   .enable_sign(enable_sign),
			   .enable_pair(enable_pair),
			   //.end_flag(sign_end_flag),
			   .state(state_sign),
			   .next_state(next_state_sign),
			   .k(random_k),
			   .dA(dA),
			   //.n(n),
			   .t1(t1),
			   .t2(t2),
			   .t3(t3),
			   .t7(t7),
			   .ss(sign_ss),
			   .s(sign_s),
			   .r(sign_r),
			   .Hv_done(Hv_done),
			   //.sha512_done(sha512_done),
			   //.sm3_done(sm3_done),
			   .INV_end_flag(INV_end_flag),
			   .ML_end_flag(ML_end_flag),
			   .ML_enable(sign_ML_enable),
			   .r_sel(sign_r_sel),
			   //.M_sel_a(sign_M_sel_a),
			   //.M_sel_b(sign_M_sel_b),
			   .A_sel_a(sign_A_sel_a),
			   .A_sel_b(sign_A_sel_b),
			   .I_sel(sign_I_sel),
			   .INV_enable(sign_INV_enable),
			   //.func(sign_func),
			   //.modn(modn),
			   .func(sign_func),
			   .re_t1(re_t1),
			   .re_t7(re_t7)
			   //.checks_no(sign_checks_no)
			  );
			  
verify_sign verify(.clk(clk),
				   .rst_n(rst_n),
				   .curve_sel(curve_sel),
				   .enable(enable_verify),
				   //.end_flag(verify_end_flag),
				   .state(state_verify),
				   .next_state(next_state_verify),
				   //.n(n),
				   .s(s_verify),
				   .r(r_verify),
				   //.bingo(verify_bingo),
				   //.invalid(verify_invalid),
				   //.sha512_done(sha512_done),
				   //.sm3_done(sm3_done),
				   //.sm3_r(sm3_r),
				   .Hv_done(Hv_done),
				   .Hv_r(Hv_r),
				   .ML_end_flag(ML_end_flag),
				   .ML_enable(verify_ML_enable),
				   .INV_end_flag(INV_end_flag),
				   .INV_enable(verify_INV_enable),
				   .I_sel(verify_I_sel),
				   .MM_end_flag(MM_end_flag),
				   .MM_enable(verify_MM_enable),
				   .func(verify_func),
				   .r_sel(verify_r_sel),
				   .M_sel_a(verify_M_sel_a),
				   .M_sel_b(verify_M_sel_b),
				   .A_sel_a(verify_A_sel_a),
				   .A_sel_b(verify_A_sel_b),
				   .t1(t1),
				   .t3(t3),
				   .t4(t4),
				   .t5(t5),
				   .t7(t7),
				   .sm3_e(sm3_e),
				   .k1(verify_k1),
				   .k2(verify_k2),
				   .kg_y(verify_kg_y),
				   .checkRr_no(verify_checkRr_no)
				  );

endmodule
